Page 1 of 1

Problem using multiple projects in MSCV

Posted: Sat May 03, 2008 11:23 am
by Andyhhp
Hi,

I am having problems getting multiple projects to work in MSCV. I have a Kernel project creating the kernel dll and a Hal project that creates a static library that is linked in with the kernel.

My problem is that I get 'Unresolved external symbol' linker error, even though the linker claims to have loaded the Hal library and extracted the relevant functions.

I have copied the settings from Demo7 exactly (well - all possibly relevant settings). The linking between Demo7 Lib and Kernel is what I am trying to achieve but I am out of ideas of what is wrong.

Here is my build output, using verbose mode.

Code: Select all

1>------ Build started: Project: Kernel, Configuration: Release Win32 ------
1>Compiling...
1>setup.cpp
1>Linking...
1>Starting pass 1
1>Searching libraries
1>    Searching C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib:
1>      Found "void * __cdecl core::memset(void *,unsigned char,unsigned int)" (?memset@core@@YAPAXPAXEI@Z)
1>        Referenced in main.obj
1>        Loaded Hal.lib(Core.obj)
1>    Searching C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib:
1>Finished searching libraries
1>Generating .exp file
1>LINK : warning LNK4216: Exported entry point _kernel_entry
1>   Creating library a:\Kernel.lib and object a:\Kernel.exp
1>Finished generating .exp file
1>Searching libraries
1>    Searching C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib:
1>    Searching C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib:
1>Finished searching libraries
1>Finished pass 1
1>a:\Kernel.dll : warning LNK4086: entrypoint '_kernel_entry' is not __stdcall with 12 bytes of arguments; image may not run
1>Hal.lib(Core.obj) : error LNK2019: unresolved external symbol _memset referenced in function "void * __cdecl core::memset(void *,unsigned char,unsigned int)" (?memset@core@@YAPAXPAXEI@Z)
1>a:\Kernel.dll : fatal error LNK1120: 1 unresolved externals
1>Build log was saved at "file://c:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Kernel\Release\BuildLog.htm"
1>Kernel - 2 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Due to restrictions on my internet connection, I cant upload the files to be hosted online :? . However, I can email them (only 37K zipped) to anyone who wants to see what I have done wrong.

Hope someone can help,

Andrew

Posted: Sat May 03, 2008 10:18 pm
by michael
Im just guessing here but the line

Code: Select all

C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib
Looks quite suspicious to me :shock: .

Is the name of the output of one of your projects called kernel32.lib as well? Because if it is I think it is probally the order (of directories) in which Visual C++ searches for um what they called, static librarys.

Posted: Sun May 04, 2008 6:00 am
by Mike

Code: Select all

:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib\kernel32.lib
The earlier demos statically linked some windows libraries with the kernel as well. I personally recommend removing them within your project settings as they are not needed and were simply overlooked.

Because the libraries are never referenced during execution, everything will work fine with or without them. (It may cause errors during linking. I personally have not seen this though)

Code: Select all

error LNK2019: unresolved external symbol _memset referenced in function "void * __cdecl core::memset(void *,unsigned char,unsigned int)" (?memset@core@@YAPAXPAXEI@Z) 
Depending on your project properties, MSVC++ might be embedding calls to its own standard library routines. You can check this by looking at the disassembly of your routine.

Do you have optimizations off? If they are, you may need to play around with the project options a little.

If you are not sure, posting your compiler and linker command lines will let us know what some of your settings are.

Posted: Sun May 04, 2008 1:37 pm
by Andyhhp
Hi,

I am not sure why it is linking to kernel32.lib but I am not specifying it.

Here are the release commandline options for compiler and linker

Kernel:
Compiler

Code: Select all

/O1 /Oy /D "_WINDLL" /D "_MBCS" /X /FD /MT /Zp1 /GS- /GR- /FAs /Fa"Release\\" /Fo"Release\\" /Fd"Release\vc80.pdb" /W4 /nologo /c /Gd /TP /errorReport:prompt
Linker

Code: Select all

/OUT:"a:\Kernel.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:"..\Lib\\" /DLL /MANIFEST:NO /NODEFAULTLIB /MAP:"KernelMap.txt" /DRIVER /OPT:REF /OPT:ICF /ORDER:"@order.txt" /ENTRY:"kernel_entry" /BASE:"0x100000" /FIXED:No /ERRORREPORT:PROMPT "C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib"  kernel32.lib /ALIGN:512 /ignore:4086 /ignore:4096 /ignore:4254 /VERBOSE
Hal:
Compiler

Code: Select all

/O1 /Oy /D "ARCH_X86" /X /FD /MT /Zp1 /GS- /GR- /FAs /Fa"Release\\" /Fo"Release\\" /Fd"Release\vc80.pdb" /W4 /nologo /c /Gz /TP /errorReport:prompt
Librarian

Code: Select all

/OUT:"C:\Users\Andrew Cooper\Documents\OS Development\Source\Kernel\Kernel\Release\Hal.lib" /NOLOGO
I cant see a way of removing kernel32.lib from the additional library's to link. There is certainly no obvious option to disable it.

Hope this is more informative,

Andrew

Posted: Sun May 04, 2008 2:38 pm
by Mike
You seem to be linking hal.lib with all symbolic names mangled using the __stdcall calling convention and linking kernel.lib using __cdecl.

Go to kernel.lib's Project Properties->C/C++->Advanced->Calling Convention, and set it to __stdcall (/Gz)

You should also be able to resolve it using the extern "C" construct.

I don't see anything else at the moment. Insure all of your projects use the same calling convention--as they also determine how the symbolic names are generated.

Posted: Sun May 04, 2008 2:50 pm
by Andyhhp
Hi,

I switched everything to stdcall but that didn't help. I then used extern C but that didn't help either.

Then I decided to change the name from memset to test.
Then something interesting happened. The unresolved external error message has changed to the following

Code: Select all

Hal.lib(Core.obj) : error LNK2019: unresolved external symbol _memset referenced in function _test@12
1>
Here is my function definition

Code: Select all

#include "Core.h"

extern "C"
void* core::test(void* ptr,unsigned char val,unsigned int len)
{
	char *start = (char*)ptr,*end = (char*)ptr + len;
	while(start<=end)
		*(start++) = val;
	return ptr;
}
I have no idea why the linker is thinking that I am referencing memset in test

Any ideas?

Posted: Sun May 04, 2008 3:15 pm
by Mike
The compiler is indeed embedding a call to memset(). This can be verified by looking at the assembly output.

This is useually caused do to optimization settings.

Try this:

Code: Select all

//disables all optimizations
#pragma optimize ("",off)

extern "C"
void* test(void* ptr,unsigned char val,unsigned int len)
{
   char *start = (char*)ptr,*end = (char*)ptr + len;
   while(start<=end)
      *(start++) = val;
   return ptr;
}

//enables all optimizations again
#pragma optimize ("",on)
You might need to omit the last #pragma directive.

Posted: Sun May 04, 2008 3:22 pm
by Andyhhp
Hi,

Thanks - thats working now. (well compiling - working comes later)

Its strange - why would the compiler embed a call to memset, especially when the options state that no default libraries are to be used.

However, looking at the asm file, it is embedding a call.

Which optimization do you suggest if it is possibly doing to mess with things like this?

Thanks,

Andrew

Posted: Sun May 04, 2008 3:35 pm
by Mike
Its strange - why would the compiler embed a call to memset, especially when the options state that no default libraries are to be used.
Its trying to be helpful. Usually if code looks like it can be better optimized using memset(), it does.

The "no default libraries" are for the linker not compiler...This is exactally where and why your error comes up and why the linker complains, not the compiler.

The libraries are not getting linked--which is why it can't find the memset() routine ;)
Which optimization do you suggest if it is possibly doing to mess with things like this?
Usually the setting that causes this type of error is Project Properties->C/C++->Optimization->Optimization. If you set this to disable, it may have also fixed the problem. By playing around with this setting, you will see how it effects everything.

At the same time, it can also cause more problems depending on your other settings.

Posted: Sun May 04, 2008 3:38 pm
by Andyhhp
How helpful :P

I think I am going to leave everything on minimum size, and disable optimizations for the specific bits of code that that is problematic for. That way, I shouldn't hit 64K for my kernel size.

Thanks,

Andrew

Posted: Sun May 04, 2008 3:44 pm
by Mike
Andyhhp wrote:I think I am going to leave everything on minimum size, and disable optimizations for the specific bits of code that that is problematic for. That way, I shouldn't hit 64K for my kernel size.
Thats what I do :)

btw, that 64k limitation bug can be fixed in the second stage bootloader by loading it with 32bit registers instead of 16bit. This fix has been verified to work for kernels > 64K in size. I personally have not tested it yet; one of our other members did though :)

Posted: Sun May 04, 2008 3:50 pm
by Andyhhp
Do the interrupts work with 32bit registers? I was under the impression that they would only work with 16bit ones

Posted: Sun May 04, 2008 3:55 pm
by Mike
Assuming that I understand the question, then yes--they can work with 32 bit registers.

Posted: Sun May 04, 2008 6:23 pm
by pathos
Going back to the OT, this may help others with the problem:

I had a similiar problem, and what fixed it was changing the compiling order of the projects.