I found a simple Hello World program D executable is big size, about 9.2 MiB. I'm using gdc-4.8 compiler. Is this a feature or some kind of bug?
Thanks for all responses!
I guess you are statically linking against the debug versions of the standard libraries.
First, the size of the executable depends on the use of dynamic vs. static linking of the standard libraries. If you statically link your executable then debug information is another contributor to size.
In numbers (I don't have gdc at hand):
compiled with ldc2, statically linked: 315KiB
compiled with ldc2 with debug info, statically linked: 2.9MiB
compiled with dmd, dynamically linked: 51KiB
compiled with dmd with debug info, statically linked: 77KiB
As far as I know gdc does not use/support -gc-section which also contributes to executable size.
Related
I was having trouble with the linker for the embedded arm gcc compiler, and I found a tutorial somewhere online saying that I could fix my linker errors in arm-none-eabi-gcc by including the argument -specs=nosys.specs, which worked for me, and it was able to compile my code.
My chip is an ATSAM7SE256 microcontroller, which to my understanding is an arm7tdmi processor using the armv4t and thumb instruction sets, and I've been compiling my code using:
arm-none-eabi-gcc -march=armv4t -mtune=arm7tdmi -specs=nosys.specs -o <exe_name>.elf <input_files>
And the code compiles with no issue, but I have no idea if it's doing what I think it's doing.
What is the significance of a spec file? What other values can you set with -specs=, and in what situations would you want to? Is nosys.specs the value I want for a completely embedded arm microcontroller?
It is documented at: https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Overall-Options.html#Overall-Options
It is a file containing switches to override standard defaults for various build components such as the compiler, assembler and linker. For example it can be used to replace the default C library.
I have never seen it used; typically bare-metal embedded system builds explicitly specify --nostdlib then explicitly link the required library. It could be used for environment specific build environments to link other default code such as an RTOS I guess. Personally I'd rather make all that explicit on the command line that hiding it in a file somewhere.
Essentially it applies the switches specified in the file as if they were defaults, so can be used to define defaults for specific build and execution environments.
The format of the specs file is documented at https://gcc.gnu.org/onlinedocs/gcc-11.1.0/gcc/Spec-Files.html#Spec-Files
Without seeing both the linker errors and the content of the nosys.specs file in this case it is difficult to say how or why it solved your linker problem. The alternative solution of course would be to apply whatever switches are in the specs file directly.
I haven't been able to find a list of possible values for the LANGUAGE variable on the CMAKE.org site or anywhere else. Would someone please enumerate the values CMAKE recognises? I specifically need to specify Objective C++.
Just take a look at all the CMakeDetermine<Language>Compiler.cmake scripts CMake ships with.
This would result - in alphabetic order - in the following you could put in the enable_language() call:
ASM
ASM-ATT
ASM-MASM
ASM-NASM
C
CSharp
CUDA
CXX
Fortran
Java
OBJC (Objective C)
OBJCXX (Objective C++)
RC (Windows Resource Compiler)
Swift
Evaluated with CMake Version 3.16
References
enable_language()
Generic rule from makefile to CMake
Update for CMake 3.16 and later: CMake added native support for Objective-C in version 3.16. The corresponding language strings are OBJC and OBJCXX. Thanks to squareskittles for pointing this out.
Original answer: The support for languages varies across platforms.
Currently CMake supports C, CXX and Fortran out of the box on most platforms. There is also support for certain Assemblers on some platforms. For a complete list, check out the contents of the Modules/Platform folder.
The idea is that the language given to the LANGUAGE field of the project command or the enable_language command is just a string, which will then be used by CMake together with the language dependent variables to setup the build system. The Platform scripts shipping with CMake do this configuration for C and C++. In theory, one can add their own language simply by setting the correct variables (although this is quite involved and I do not know of anyone ever successfully doing this).
As for adding support for Objective-C: Since most toolchains use the same compiler for C and Objective-C, you do not need to configure a new language. Simply compile your code as if it was plain C and add the appropriate compiler flags for Objective-C support.
Unfortunately, this is not very comfortable to use and can easily break in corner cases. But until CMake adds explicit support for Objective-C as a first class language, I'm afraid this is as good as it gets.
I have tried to compile to assembler my source code with next flags:
1. -flto
2. -flto -ffat-lto-objects
3. -flto -fno-fat-lto-objects
Third one provides optimized slim LTO code as written in documentation, but I don't see any difference in the output assembly file between first and second, why?
OS: linux
Compiler: GCC 4.7
The difference between fat and non-fat object files is that fat object files contains both intermediate language as well as the normally compiled code. At linktime, if you invoke compiler without -flto, fat objects will be handled as normal object files (and LTO information discarded), while slim objects will invoke LTO optimizers because there is no way to handle them without it.
If you both compile and link with -flto, both fat and slim objects ought to give you the same binary, just slim objects will be smaller and faster to compile, because you will avoid the redundant code generation.
Probably it will be helpful to someone:
Here wrote next:
The current implementation only produces “fat” objects, effectively doubling compilation time and increasing file sizes up to 5x the original size
So as I think it's the main reason.
As mentioned in the title, this is a real beginner's question.
I'm realizing that after several years of CS courses and projects and such, I have never actually needed to export an executable that someone else could run without compiling the source manually (which is what most/all professors/TAs do, since they want to see your source code anyway).
So my question is basically this:
When I compile some basic C++ code (e.g. "Hello World" code), I always seem to need some sort of external DLLs to run it.
Visual Studio needs the .NET framework.
Cygwin needs Cygwin.dll.
MinGW needs libgcc_s_dw2-1.dll or something similar.
So how do I simply compile an executable such that I (or someone I give the file to) can just double-click it and have it run? I'm guessing there are some fancy command line flags I can use on g++ to statically link the DLLs; I have simply never needed to do this before.
As I said twice, this is a super beginner question, and yet I could not find (easily, anyway) an answer to this question, StackOverflow or anywhere else. Largely, I think, because the search terms are so commonly used in the descriptions for other problems.
Anyway, all help is appreciated.
EDIT:
I'm literally talking about a Hello World program. e.g.:
HelloWorld.cpp:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!" << endl;
return 0;
}
Try g++ -static -static-libgcc
However, you should generally avoid static linking. Almost all the utilities on a usual Linux machine are dynamically linked: you can use file or ldd to know if an executable is statically linked. On my Debian/Sid system /usr/bin/ contains 7303 files, but only one is statically linked (it is /usr/bin/rar).
Using dynamic linking is better, because it uses less disk space, and most importantly because dynamic libraries are updated, and that profit to all the executables dynamically linking them.
If you care about dependencies, use your package manager (or distribute your program as a package).
If you already got the static lib you need to link in, (.lib or .a), just put them together with the object files when you linking your application, like
g++ foo.o libfoo.a -o foo
I think your real problem is how to locate which static libs are required by your application and how to get them, maybe you should post your code here and let us know what library you need to link in.
Here is how:
simply put, you specify to link all the standard stuff into your executable.
g++ -o c:\prog.exe c:\HelloWorld.cpp -static-libgcc -static-libstdc++
hope it helps.
I have created a static library containing all my generic classes. Some of these classes use frameworks.
Now I have two projects, one that uses some classes that use frameworks, and one that doesn't use any of the classes that use frameworks.
Because Static Libraries don't support including frameworks (if I am correct). I have to include the frameworks in the project that uses them. But when I compile the project that doesn't use any of the framework-classes the compiler breaks because it still requires the frameworks. Now I know it tries to compile all the (unused) classes from the library because I use the Linker Flag '-ObjC' to prevent 'unrecognized selector' errors.
Does anyone know how to compile only the required source files per project? And prevent from all frameworks having to be included in all projects that use my static library?
First of all, you are right in that a static library cannot include any framework nor other static libraries, it is just the collection of all object files (*.obj) that make up that specific static library.
Does anyone know how to compile only the required source files per project?
The linker will by default only link in object files from the static library that contain symbols referenced by the application. So, if you have two files a.m and b.m in your static library and you only use symbols from a.m in your main program, then b.o (the object file generated from b.c) will not appear in your final executable. As a sub-case, if b.m uses a function/class c which is only declared (not implemented), then you will not get any linker errors. As soon as you include some symbols from b.m in your program, b.o will also be linked and you will get linker errors due to the missing implementation of c.
If you want this kind of selection to happen at symbol rather than at object level granularity, enable dead code stripping in Xcode. This corresponds to the gcc option -Wl,-dead_strip (= linker option -dead_strip in the Build settings Info pane for your project). This would ensure further optimization.
In your case, though, as you correctly say, it is the use of the "-ObjC" linker flag that defeats this mechanism. So this actually depends on you. If you remove the -Objc flag, you get the behavior you like for free, while losing the stricter check on selectors.
And prevent from all frameworks having to be included in all projects that use my static library?
Xcode/GCC support an linking option which is called "weak linking", which allows to lazily load a framework or static library, i.e., only when one of its symbols is actually used.
"weak linking" can be enabled either through a linker flag (see Apple doc above), or through Xcode UI (Target -> Info -> General -> Linked Libraries).
Anyhow, the framework or library must be available in all cases at compile/link time: the "weak" option only affects the moment when the framework is first loaded at runtime. Thus, I don't think this is useful for you, since you would need anyway to include the framework in all of your projects, which is what you do not want.
As a side note, weak_linking is an option that mostly make sense when using features only available on newer SDK version (say, 4.3.2) while also supporting deployment on older SDK versions (say, 3.1.3). In this case, you rely on the fact that the newer SDK frameworks will be actually available on the newer deployment devices, and you conditionally compile in the features requiring it, so that on older devices they will not be required (and will not produce thus the attempt at loading the newer version of the framework and the crash).
To make things worse, GCC does not support a feature known as "auto-linking" with Microsoft compilers, which allow to specify which library to link by means of a #pragma comment in your source file. This could offer a workaround, but is not there.
So, I am really sorry to have to say that you should use a different approach that could equally satisfy your needs:
remove the -ObjC flag;
split your static library in two or more parts according to their dependencies from external frameworks;
resort to including the source files directly.
Abour second part of your question, you can mark a linked framework as Optional :
About first part, it is not clear to me what you intend to do:
A library being declared in a project
A project declaring which files are compiled (via Target > Build phases > Compile sources)
Unless setting complex build rules to include or not files, which if I remember well can be done using .xcconfig files, I don't see any other solutions than splitting your Library. Which I would recommend, for its ease. You should even do several targets in the same project... You could also just use precompiler MACROS (#ifdef...) but that depends on what you want to do.
It sounds like you have library bloat. To keep things small I think you need to refactor your library into separate libraries with minimal dependencies. You could try turning on "Dead Code Stripping" in the "Linker Flags" section of the build target info (Xcode 3.x) to see if that does what you want (doesn't require frameworks used by classes that are dead-stripped.)
When you link against a framework on iOS I don't think that really adds any bloat since the framework is on the device and not in your application. But your library is still a bit bloated by having entire classes that never get used but are not stripped out of the library.
A static library is built before your app is compiled, and then the whole thing is linked into your app. There's no way to include some parts of the library but not others -- you get the whole enchilada.
Since you have the source code for the library, why not just add the code directly to each application? That way you can control exactly what goes into each app. You can still keep your generic classes together in the same location, and use the same code in both apps, but you avoid the hassle of using a library.