Compiling C/C++ code by way of including preprocessor build instructions in an actual C/C++ source file
Clash Royale CLAN TAG#URR8PPP
I've got reasons for not wanting to rely on a specific build system. I don't mean to dis anybody's favorite, but I really just want to stick to what comes with the compiler. In this case, GCC. Automake has certain compatibility issues, especially with Windows. <3 GNU make is so limited that it often needs to be supplemented with shell scripts. Shell scripts can take many forms, and to make a long story short and probably piss a lot of people off, here is what I want to do --
The main entry point is God. Be it a C or C++ source file, it is the center of the application. Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled. Let me explain --
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over. Any library that needs to be dynamically linked can be included as a supporting file of the application. For that reason, separate build instructions for .SOs (and maybe .DLLs ;]) is all fine and dandy, because they are separate executable files. Any other library should be statically linked. Now, let's talk about static linking --
Static linking is a real bitch. That's what makefiles are for. If the whole project was written in one language (for instance C OR C++), you can #include the libraries as headers. That's just fine. But now, let's consider another scenario --
Let's say you're like me and can't be arsed to figure out C's difficult excuse for strings, so you decide to use C++. But you want to use a C library, like for instance MiniBasic. God help us. If the C library wasn't designed to conform to C++'s syntax, you're screwed. That's when makefiles come in, since you need to compile the C source file with a C compiler and the C++ source file with a C++ compiler. I don't want to use makefiles.
I would hope that there is a way to exploit GCC's preprocessor macros to tell it something like this:
Hi, GCC. How are you doing? In case you forgot, this source file you're looking at right now is written in C++. You should of course compile it with G++. There's another file that this file needs, but it's written in C. It's called "lolcats.c". I want you to compile that one with GCC into an object file and I want you to compile this one with G++ into the main object file, then I want you to link them together into an executable file.
How might I write such a thing in preprocessor lingo? Does GCC even do that?
gcc c++ programming linker static-linking
add a comment |
I've got reasons for not wanting to rely on a specific build system. I don't mean to dis anybody's favorite, but I really just want to stick to what comes with the compiler. In this case, GCC. Automake has certain compatibility issues, especially with Windows. <3 GNU make is so limited that it often needs to be supplemented with shell scripts. Shell scripts can take many forms, and to make a long story short and probably piss a lot of people off, here is what I want to do --
The main entry point is God. Be it a C or C++ source file, it is the center of the application. Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled. Let me explain --
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over. Any library that needs to be dynamically linked can be included as a supporting file of the application. For that reason, separate build instructions for .SOs (and maybe .DLLs ;]) is all fine and dandy, because they are separate executable files. Any other library should be statically linked. Now, let's talk about static linking --
Static linking is a real bitch. That's what makefiles are for. If the whole project was written in one language (for instance C OR C++), you can #include the libraries as headers. That's just fine. But now, let's consider another scenario --
Let's say you're like me and can't be arsed to figure out C's difficult excuse for strings, so you decide to use C++. But you want to use a C library, like for instance MiniBasic. God help us. If the C library wasn't designed to conform to C++'s syntax, you're screwed. That's when makefiles come in, since you need to compile the C source file with a C compiler and the C++ source file with a C++ compiler. I don't want to use makefiles.
I would hope that there is a way to exploit GCC's preprocessor macros to tell it something like this:
Hi, GCC. How are you doing? In case you forgot, this source file you're looking at right now is written in C++. You should of course compile it with G++. There's another file that this file needs, but it's written in C. It's called "lolcats.c". I want you to compile that one with GCC into an object file and I want you to compile this one with G++ into the main object file, then I want you to link them together into an executable file.
How might I write such a thing in preprocessor lingo? Does GCC even do that?
gcc c++ programming linker static-linking
You could decide that all your things are plugins.
– Basile Starynkevitch
Jul 20 '14 at 11:29
3
Your question is unclear.
– Basile Starynkevitch
Jul 20 '14 at 11:39
add a comment |
I've got reasons for not wanting to rely on a specific build system. I don't mean to dis anybody's favorite, but I really just want to stick to what comes with the compiler. In this case, GCC. Automake has certain compatibility issues, especially with Windows. <3 GNU make is so limited that it often needs to be supplemented with shell scripts. Shell scripts can take many forms, and to make a long story short and probably piss a lot of people off, here is what I want to do --
The main entry point is God. Be it a C or C++ source file, it is the center of the application. Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled. Let me explain --
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over. Any library that needs to be dynamically linked can be included as a supporting file of the application. For that reason, separate build instructions for .SOs (and maybe .DLLs ;]) is all fine and dandy, because they are separate executable files. Any other library should be statically linked. Now, let's talk about static linking --
Static linking is a real bitch. That's what makefiles are for. If the whole project was written in one language (for instance C OR C++), you can #include the libraries as headers. That's just fine. But now, let's consider another scenario --
Let's say you're like me and can't be arsed to figure out C's difficult excuse for strings, so you decide to use C++. But you want to use a C library, like for instance MiniBasic. God help us. If the C library wasn't designed to conform to C++'s syntax, you're screwed. That's when makefiles come in, since you need to compile the C source file with a C compiler and the C++ source file with a C++ compiler. I don't want to use makefiles.
I would hope that there is a way to exploit GCC's preprocessor macros to tell it something like this:
Hi, GCC. How are you doing? In case you forgot, this source file you're looking at right now is written in C++. You should of course compile it with G++. There's another file that this file needs, but it's written in C. It's called "lolcats.c". I want you to compile that one with GCC into an object file and I want you to compile this one with G++ into the main object file, then I want you to link them together into an executable file.
How might I write such a thing in preprocessor lingo? Does GCC even do that?
gcc c++ programming linker static-linking
I've got reasons for not wanting to rely on a specific build system. I don't mean to dis anybody's favorite, but I really just want to stick to what comes with the compiler. In this case, GCC. Automake has certain compatibility issues, especially with Windows. <3 GNU make is so limited that it often needs to be supplemented with shell scripts. Shell scripts can take many forms, and to make a long story short and probably piss a lot of people off, here is what I want to do --
The main entry point is God. Be it a C or C++ source file, it is the center of the application. Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled. Let me explain --
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over. Any library that needs to be dynamically linked can be included as a supporting file of the application. For that reason, separate build instructions for .SOs (and maybe .DLLs ;]) is all fine and dandy, because they are separate executable files. Any other library should be statically linked. Now, let's talk about static linking --
Static linking is a real bitch. That's what makefiles are for. If the whole project was written in one language (for instance C OR C++), you can #include the libraries as headers. That's just fine. But now, let's consider another scenario --
Let's say you're like me and can't be arsed to figure out C's difficult excuse for strings, so you decide to use C++. But you want to use a C library, like for instance MiniBasic. God help us. If the C library wasn't designed to conform to C++'s syntax, you're screwed. That's when makefiles come in, since you need to compile the C source file with a C compiler and the C++ source file with a C++ compiler. I don't want to use makefiles.
I would hope that there is a way to exploit GCC's preprocessor macros to tell it something like this:
Hi, GCC. How are you doing? In case you forgot, this source file you're looking at right now is written in C++. You should of course compile it with G++. There's another file that this file needs, but it's written in C. It's called "lolcats.c". I want you to compile that one with GCC into an object file and I want you to compile this one with G++ into the main object file, then I want you to link them together into an executable file.
How might I write such a thing in preprocessor lingo? Does GCC even do that?
gcc c++ programming linker static-linking
gcc c++ programming linker static-linking
edited Jan 13 at 22:19
Rui F Ribeiro
39.7k1479132
39.7k1479132
asked Jul 20 '14 at 2:03
user78076user78076
124
124
You could decide that all your things are plugins.
– Basile Starynkevitch
Jul 20 '14 at 11:29
3
Your question is unclear.
– Basile Starynkevitch
Jul 20 '14 at 11:39
add a comment |
You could decide that all your things are plugins.
– Basile Starynkevitch
Jul 20 '14 at 11:29
3
Your question is unclear.
– Basile Starynkevitch
Jul 20 '14 at 11:39
You could decide that all your things are plugins.
– Basile Starynkevitch
Jul 20 '14 at 11:29
You could decide that all your things are plugins.
– Basile Starynkevitch
Jul 20 '14 at 11:29
3
3
Your question is unclear.
– Basile Starynkevitch
Jul 20 '14 at 11:39
Your question is unclear.
– Basile Starynkevitch
Jul 20 '14 at 11:39
add a comment |
4 Answers
4
active
oldest
votes
The main entry point is God. Be it a C or C++ source file, it is the center of the application.
Only in the same way that nitrogen is the center of a pine tree. It is where everything starts, but there's nothing about C or C++ that makes you put the "center" of your application in main()
.
A great many C and C++ programs are built on an event loop or an I/O pump. These are the "centers" of such programs. You don't even have to put these loops in the same module as main()
.
Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled.
It is actually easiest to put main()
last in a C or C++ source file.
C and C++ are not like some languages, where symbols can be used before they are declared. Putting main()
first means you have to forward-declare everything else.
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over.
"Tell 'im 'e's dreamin'!"
OS X and iOS are full of proprietary code, and Microsoft isn't going away any time soon.
What do Microsoft's current difficulties have to do with your question, anyway? You say you might want to make DLLs, and you mention Automake's inability to cope effectively with Windows. That tells me Microsoft remains relevant in your world, too.
Static linking is a real bitch.
Really? I've always found it easier than linking to dynamic libraries. It's an older, simpler technology, with fewer things to go wrong.
Static linking incorporates the external dependencies into the executable, so that the executable stands alone, self-contained. From the rest of your question, that should appeal to you.
you can #include the libraries as headers
No... You #include
library headers, not libraries.
This isn't just pedantry. The terminology matters. It has meaning.
If you could #include
libraries, #include </usr/lib/libfoo.a>
would work.
In many programming languages, that is the way external module/library references work. That is, you reference the external code directly.
C and C++ are not among the languages that work that way.
If the C library wasn't designed to conform to C++'s syntax, you're screwed.
No, you just have to learn to use C++. Specifically here, extern "C"
.
How might I write such a thing in preprocessor lingo?
It is perfectly legal to #include
another C or C++ file:
#include <some/library/main.cpp>
#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>
#include <iostream>
int main()
call_the_library();
do_other_stuff();
return 0;
We don't use extern "C"
here because this pulls the C and C++ code from those other libraries directly into our C++ file, so the C modules need to be legal C++ as well. There are a number of annoying little differences between C and C++, but if you're going to intermix the two languages, you're going to have to know how to cope with them regardless.
Another tricky part of doing this is that the order of the #includes
is more sensitive than the order of library references if a linker command. When you bypass the linker in this way, you end up having to do some things manually that the linker would otherwise do for you automatically.
To prove the point, I took MiniBasic (your own example) and converted its script.c
driver program to a standalone C++ program that says #include <basic.c>
instead of #include <basic.h>
. (patch) Just to prove that it's really a C++ program now, I changed all the printf()
calls to cout
stream insertions.
I had to make a few other changes, all of them well within a normal day's work for someone who's going to intermix C and C++:
The MiniBasic code makes use of C's willingness to tolerate automatic conversions from
void*
to any other pointer type. C++ makes you be explicit.Newer compilers are no longer tolerating use of C string constants (e.g.
"Hello, world!n"
) inchar*
contexts. The standard says the compiler is allowed to place them into read-only memory, so you need to useconst char*
.
That's it. Just a few minutes work, patching GCC complaints.
I had to make some similar changes in basic.c
to those in the linked script.c
patch file. I haven't bothered posting the diffs, since they're just more of the same.
For another way to go about this, study the SQLite Amalgamation, as compared to the SQLite source tree. SQLite doesn't use #include
all the other files into a single master file; they're actually concatenated together, but that is also all #include
does in C or C++.
add a comment |
gcc will compile C and C and C++ as C++ simply as a result of you naming the files appropriately, the preprocessor doesn't come into that. You'll need extern "C"
blocks around your C declarations in your C++ files to make sure the linker can link stuff correctly, though.
But what you're describing is almost never going to be helpful. If you're using a library that needs some kind of configuration to compile in the first place, then it's still going to need it if you just try to compile the files directly into your project. Not many real-world non-trivial libraries are pure ISO C that will compile on every platform without modification or some kind of configure script, so you'd be creating complexity most of the time, not reducing it, because you're going to have to deal with that configuration in your own build somehow.
add a comment |
No, you can't do that. There's no gcc pragma for compile in this way.
The most similar is the Microsoft Visual C++ #pragma comment(lib, …)
or #pragma comment(linker, …)
[1] [2] for noting that some libraries should be included in the link procedure.
Hi, GCC. How are you doing? In case you forgot, this source file
you're looking at right now is written in C++. You should of course
compile it with G++. There's another file that this file needs, but
it's written in C. It's called "lolcats.c". I want you to compile that
one with GCC into an object file and I want you to compile this one
with G++ into the main object file, then I want you to link them
together into an executable file.
Your request is exactly what a Makefile does.
You could create a shell script that extracts the source files and compiles them with whatever command you want to use. But it's The Wrong Solution™
If you have multiple files, store them as multiple files. If you want people not to use make or cmake, don't provide a Makefile
/CMakefile
. Give them for instance a compile-me.sh
file.
The only case when I feel I am in a similar situation is whan I code a util in a single file, but I simply provide the compilation command at the top inside a comment.
add a comment |
You could decide that all your things are plugins. Then compile them with gcc -shared -fPIC -O thing1.cc -o thing1.so
and have a main stub program doing dlopen(3) on ./thing1.so
then dlsym
on God
; on Linux you could have binfmt_misc tricks to make that more transparent.
If you insist on having self-containing programs, notice that GCC has the -ffreestanding option. It is then up to you to provide a runtime environment (at the very least, for some basic I/O thru system calls which you would need to interface, see syscalls(2)). Study carefully the relevant ABI spec. For Linux/x86-64 it is here. Read about calling conventions.
You could also customize GCC with compiler plugins like MELT (then you could add a #pragma
which would do arbitrary things, perhaps even forking a gcc
...)
BTW, an entry point like your God
is not a source file, but some label known to the linker.
Reading more about compilers, linkers (see Levine's book: Linkers and Loaders, object files, ELF, libraries and shared objects (see Drepper's paper: How to Write Shared Libraries ...), crt0.o should help.
See also the C++ module draft proposal N3347
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f145527%2fcompiling-c-c-code-by-way-of-including-preprocessor-build-instructions-in-an-a%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
The main entry point is God. Be it a C or C++ source file, it is the center of the application.
Only in the same way that nitrogen is the center of a pine tree. It is where everything starts, but there's nothing about C or C++ that makes you put the "center" of your application in main()
.
A great many C and C++ programs are built on an event loop or an I/O pump. These are the "centers" of such programs. You don't even have to put these loops in the same module as main()
.
Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled.
It is actually easiest to put main()
last in a C or C++ source file.
C and C++ are not like some languages, where symbols can be used before they are declared. Putting main()
first means you have to forward-declare everything else.
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over.
"Tell 'im 'e's dreamin'!"
OS X and iOS are full of proprietary code, and Microsoft isn't going away any time soon.
What do Microsoft's current difficulties have to do with your question, anyway? You say you might want to make DLLs, and you mention Automake's inability to cope effectively with Windows. That tells me Microsoft remains relevant in your world, too.
Static linking is a real bitch.
Really? I've always found it easier than linking to dynamic libraries. It's an older, simpler technology, with fewer things to go wrong.
Static linking incorporates the external dependencies into the executable, so that the executable stands alone, self-contained. From the rest of your question, that should appeal to you.
you can #include the libraries as headers
No... You #include
library headers, not libraries.
This isn't just pedantry. The terminology matters. It has meaning.
If you could #include
libraries, #include </usr/lib/libfoo.a>
would work.
In many programming languages, that is the way external module/library references work. That is, you reference the external code directly.
C and C++ are not among the languages that work that way.
If the C library wasn't designed to conform to C++'s syntax, you're screwed.
No, you just have to learn to use C++. Specifically here, extern "C"
.
How might I write such a thing in preprocessor lingo?
It is perfectly legal to #include
another C or C++ file:
#include <some/library/main.cpp>
#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>
#include <iostream>
int main()
call_the_library();
do_other_stuff();
return 0;
We don't use extern "C"
here because this pulls the C and C++ code from those other libraries directly into our C++ file, so the C modules need to be legal C++ as well. There are a number of annoying little differences between C and C++, but if you're going to intermix the two languages, you're going to have to know how to cope with them regardless.
Another tricky part of doing this is that the order of the #includes
is more sensitive than the order of library references if a linker command. When you bypass the linker in this way, you end up having to do some things manually that the linker would otherwise do for you automatically.
To prove the point, I took MiniBasic (your own example) and converted its script.c
driver program to a standalone C++ program that says #include <basic.c>
instead of #include <basic.h>
. (patch) Just to prove that it's really a C++ program now, I changed all the printf()
calls to cout
stream insertions.
I had to make a few other changes, all of them well within a normal day's work for someone who's going to intermix C and C++:
The MiniBasic code makes use of C's willingness to tolerate automatic conversions from
void*
to any other pointer type. C++ makes you be explicit.Newer compilers are no longer tolerating use of C string constants (e.g.
"Hello, world!n"
) inchar*
contexts. The standard says the compiler is allowed to place them into read-only memory, so you need to useconst char*
.
That's it. Just a few minutes work, patching GCC complaints.
I had to make some similar changes in basic.c
to those in the linked script.c
patch file. I haven't bothered posting the diffs, since they're just more of the same.
For another way to go about this, study the SQLite Amalgamation, as compared to the SQLite source tree. SQLite doesn't use #include
all the other files into a single master file; they're actually concatenated together, but that is also all #include
does in C or C++.
add a comment |
The main entry point is God. Be it a C or C++ source file, it is the center of the application.
Only in the same way that nitrogen is the center of a pine tree. It is where everything starts, but there's nothing about C or C++ that makes you put the "center" of your application in main()
.
A great many C and C++ programs are built on an event loop or an I/O pump. These are the "centers" of such programs. You don't even have to put these loops in the same module as main()
.
Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled.
It is actually easiest to put main()
last in a C or C++ source file.
C and C++ are not like some languages, where symbols can be used before they are declared. Putting main()
first means you have to forward-declare everything else.
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over.
"Tell 'im 'e's dreamin'!"
OS X and iOS are full of proprietary code, and Microsoft isn't going away any time soon.
What do Microsoft's current difficulties have to do with your question, anyway? You say you might want to make DLLs, and you mention Automake's inability to cope effectively with Windows. That tells me Microsoft remains relevant in your world, too.
Static linking is a real bitch.
Really? I've always found it easier than linking to dynamic libraries. It's an older, simpler technology, with fewer things to go wrong.
Static linking incorporates the external dependencies into the executable, so that the executable stands alone, self-contained. From the rest of your question, that should appeal to you.
you can #include the libraries as headers
No... You #include
library headers, not libraries.
This isn't just pedantry. The terminology matters. It has meaning.
If you could #include
libraries, #include </usr/lib/libfoo.a>
would work.
In many programming languages, that is the way external module/library references work. That is, you reference the external code directly.
C and C++ are not among the languages that work that way.
If the C library wasn't designed to conform to C++'s syntax, you're screwed.
No, you just have to learn to use C++. Specifically here, extern "C"
.
How might I write such a thing in preprocessor lingo?
It is perfectly legal to #include
another C or C++ file:
#include <some/library/main.cpp>
#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>
#include <iostream>
int main()
call_the_library();
do_other_stuff();
return 0;
We don't use extern "C"
here because this pulls the C and C++ code from those other libraries directly into our C++ file, so the C modules need to be legal C++ as well. There are a number of annoying little differences between C and C++, but if you're going to intermix the two languages, you're going to have to know how to cope with them regardless.
Another tricky part of doing this is that the order of the #includes
is more sensitive than the order of library references if a linker command. When you bypass the linker in this way, you end up having to do some things manually that the linker would otherwise do for you automatically.
To prove the point, I took MiniBasic (your own example) and converted its script.c
driver program to a standalone C++ program that says #include <basic.c>
instead of #include <basic.h>
. (patch) Just to prove that it's really a C++ program now, I changed all the printf()
calls to cout
stream insertions.
I had to make a few other changes, all of them well within a normal day's work for someone who's going to intermix C and C++:
The MiniBasic code makes use of C's willingness to tolerate automatic conversions from
void*
to any other pointer type. C++ makes you be explicit.Newer compilers are no longer tolerating use of C string constants (e.g.
"Hello, world!n"
) inchar*
contexts. The standard says the compiler is allowed to place them into read-only memory, so you need to useconst char*
.
That's it. Just a few minutes work, patching GCC complaints.
I had to make some similar changes in basic.c
to those in the linked script.c
patch file. I haven't bothered posting the diffs, since they're just more of the same.
For another way to go about this, study the SQLite Amalgamation, as compared to the SQLite source tree. SQLite doesn't use #include
all the other files into a single master file; they're actually concatenated together, but that is also all #include
does in C or C++.
add a comment |
The main entry point is God. Be it a C or C++ source file, it is the center of the application.
Only in the same way that nitrogen is the center of a pine tree. It is where everything starts, but there's nothing about C or C++ that makes you put the "center" of your application in main()
.
A great many C and C++ programs are built on an event loop or an I/O pump. These are the "centers" of such programs. You don't even have to put these loops in the same module as main()
.
Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled.
It is actually easiest to put main()
last in a C or C++ source file.
C and C++ are not like some languages, where symbols can be used before they are declared. Putting main()
first means you have to forward-declare everything else.
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over.
"Tell 'im 'e's dreamin'!"
OS X and iOS are full of proprietary code, and Microsoft isn't going away any time soon.
What do Microsoft's current difficulties have to do with your question, anyway? You say you might want to make DLLs, and you mention Automake's inability to cope effectively with Windows. That tells me Microsoft remains relevant in your world, too.
Static linking is a real bitch.
Really? I've always found it easier than linking to dynamic libraries. It's an older, simpler technology, with fewer things to go wrong.
Static linking incorporates the external dependencies into the executable, so that the executable stands alone, self-contained. From the rest of your question, that should appeal to you.
you can #include the libraries as headers
No... You #include
library headers, not libraries.
This isn't just pedantry. The terminology matters. It has meaning.
If you could #include
libraries, #include </usr/lib/libfoo.a>
would work.
In many programming languages, that is the way external module/library references work. That is, you reference the external code directly.
C and C++ are not among the languages that work that way.
If the C library wasn't designed to conform to C++'s syntax, you're screwed.
No, you just have to learn to use C++. Specifically here, extern "C"
.
How might I write such a thing in preprocessor lingo?
It is perfectly legal to #include
another C or C++ file:
#include <some/library/main.cpp>
#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>
#include <iostream>
int main()
call_the_library();
do_other_stuff();
return 0;
We don't use extern "C"
here because this pulls the C and C++ code from those other libraries directly into our C++ file, so the C modules need to be legal C++ as well. There are a number of annoying little differences between C and C++, but if you're going to intermix the two languages, you're going to have to know how to cope with them regardless.
Another tricky part of doing this is that the order of the #includes
is more sensitive than the order of library references if a linker command. When you bypass the linker in this way, you end up having to do some things manually that the linker would otherwise do for you automatically.
To prove the point, I took MiniBasic (your own example) and converted its script.c
driver program to a standalone C++ program that says #include <basic.c>
instead of #include <basic.h>
. (patch) Just to prove that it's really a C++ program now, I changed all the printf()
calls to cout
stream insertions.
I had to make a few other changes, all of them well within a normal day's work for someone who's going to intermix C and C++:
The MiniBasic code makes use of C's willingness to tolerate automatic conversions from
void*
to any other pointer type. C++ makes you be explicit.Newer compilers are no longer tolerating use of C string constants (e.g.
"Hello, world!n"
) inchar*
contexts. The standard says the compiler is allowed to place them into read-only memory, so you need to useconst char*
.
That's it. Just a few minutes work, patching GCC complaints.
I had to make some similar changes in basic.c
to those in the linked script.c
patch file. I haven't bothered posting the diffs, since they're just more of the same.
For another way to go about this, study the SQLite Amalgamation, as compared to the SQLite source tree. SQLite doesn't use #include
all the other files into a single master file; they're actually concatenated together, but that is also all #include
does in C or C++.
The main entry point is God. Be it a C or C++ source file, it is the center of the application.
Only in the same way that nitrogen is the center of a pine tree. It is where everything starts, but there's nothing about C or C++ that makes you put the "center" of your application in main()
.
A great many C and C++ programs are built on an event loop or an I/O pump. These are the "centers" of such programs. You don't even have to put these loops in the same module as main()
.
Not only do I want the main entry point to be the first thing that is executed, I also want it to be the first thing that is compiled.
It is actually easiest to put main()
last in a C or C++ source file.
C and C++ are not like some languages, where symbols can be used before they are declared. Putting main()
first means you have to forward-declare everything else.
There was a time when proprietary and closed-source libraries were common. Thanks to Apple switching to Unix and Microsoft shooting themselves in the foot, that time is over.
"Tell 'im 'e's dreamin'!"
OS X and iOS are full of proprietary code, and Microsoft isn't going away any time soon.
What do Microsoft's current difficulties have to do with your question, anyway? You say you might want to make DLLs, and you mention Automake's inability to cope effectively with Windows. That tells me Microsoft remains relevant in your world, too.
Static linking is a real bitch.
Really? I've always found it easier than linking to dynamic libraries. It's an older, simpler technology, with fewer things to go wrong.
Static linking incorporates the external dependencies into the executable, so that the executable stands alone, self-contained. From the rest of your question, that should appeal to you.
you can #include the libraries as headers
No... You #include
library headers, not libraries.
This isn't just pedantry. The terminology matters. It has meaning.
If you could #include
libraries, #include </usr/lib/libfoo.a>
would work.
In many programming languages, that is the way external module/library references work. That is, you reference the external code directly.
C and C++ are not among the languages that work that way.
If the C library wasn't designed to conform to C++'s syntax, you're screwed.
No, you just have to learn to use C++. Specifically here, extern "C"
.
How might I write such a thing in preprocessor lingo?
It is perfectly legal to #include
another C or C++ file:
#include <some/library/main.cpp>
#include <some/other/library/main.c>
#include <some/other/library/secondary_module.c>
#include <iostream>
int main()
call_the_library();
do_other_stuff();
return 0;
We don't use extern "C"
here because this pulls the C and C++ code from those other libraries directly into our C++ file, so the C modules need to be legal C++ as well. There are a number of annoying little differences between C and C++, but if you're going to intermix the two languages, you're going to have to know how to cope with them regardless.
Another tricky part of doing this is that the order of the #includes
is more sensitive than the order of library references if a linker command. When you bypass the linker in this way, you end up having to do some things manually that the linker would otherwise do for you automatically.
To prove the point, I took MiniBasic (your own example) and converted its script.c
driver program to a standalone C++ program that says #include <basic.c>
instead of #include <basic.h>
. (patch) Just to prove that it's really a C++ program now, I changed all the printf()
calls to cout
stream insertions.
I had to make a few other changes, all of them well within a normal day's work for someone who's going to intermix C and C++:
The MiniBasic code makes use of C's willingness to tolerate automatic conversions from
void*
to any other pointer type. C++ makes you be explicit.Newer compilers are no longer tolerating use of C string constants (e.g.
"Hello, world!n"
) inchar*
contexts. The standard says the compiler is allowed to place them into read-only memory, so you need to useconst char*
.
That's it. Just a few minutes work, patching GCC complaints.
I had to make some similar changes in basic.c
to those in the linked script.c
patch file. I haven't bothered posting the diffs, since they're just more of the same.
For another way to go about this, study the SQLite Amalgamation, as compared to the SQLite source tree. SQLite doesn't use #include
all the other files into a single master file; they're actually concatenated together, but that is also all #include
does in C or C++.
edited Aug 5 '14 at 17:29
answered Jul 20 '14 at 3:18
Warren YoungWarren Young
55k11143147
55k11143147
add a comment |
add a comment |
gcc will compile C and C and C++ as C++ simply as a result of you naming the files appropriately, the preprocessor doesn't come into that. You'll need extern "C"
blocks around your C declarations in your C++ files to make sure the linker can link stuff correctly, though.
But what you're describing is almost never going to be helpful. If you're using a library that needs some kind of configuration to compile in the first place, then it's still going to need it if you just try to compile the files directly into your project. Not many real-world non-trivial libraries are pure ISO C that will compile on every platform without modification or some kind of configure script, so you'd be creating complexity most of the time, not reducing it, because you're going to have to deal with that configuration in your own build somehow.
add a comment |
gcc will compile C and C and C++ as C++ simply as a result of you naming the files appropriately, the preprocessor doesn't come into that. You'll need extern "C"
blocks around your C declarations in your C++ files to make sure the linker can link stuff correctly, though.
But what you're describing is almost never going to be helpful. If you're using a library that needs some kind of configuration to compile in the first place, then it's still going to need it if you just try to compile the files directly into your project. Not many real-world non-trivial libraries are pure ISO C that will compile on every platform without modification or some kind of configure script, so you'd be creating complexity most of the time, not reducing it, because you're going to have to deal with that configuration in your own build somehow.
add a comment |
gcc will compile C and C and C++ as C++ simply as a result of you naming the files appropriately, the preprocessor doesn't come into that. You'll need extern "C"
blocks around your C declarations in your C++ files to make sure the linker can link stuff correctly, though.
But what you're describing is almost never going to be helpful. If you're using a library that needs some kind of configuration to compile in the first place, then it's still going to need it if you just try to compile the files directly into your project. Not many real-world non-trivial libraries are pure ISO C that will compile on every platform without modification or some kind of configure script, so you'd be creating complexity most of the time, not reducing it, because you're going to have to deal with that configuration in your own build somehow.
gcc will compile C and C and C++ as C++ simply as a result of you naming the files appropriately, the preprocessor doesn't come into that. You'll need extern "C"
blocks around your C declarations in your C++ files to make sure the linker can link stuff correctly, though.
But what you're describing is almost never going to be helpful. If you're using a library that needs some kind of configuration to compile in the first place, then it's still going to need it if you just try to compile the files directly into your project. Not many real-world non-trivial libraries are pure ISO C that will compile on every platform without modification or some kind of configure script, so you'd be creating complexity most of the time, not reducing it, because you're going to have to deal with that configuration in your own build somehow.
answered Jul 20 '14 at 3:57
Paul GriffithsPaul Griffiths
1514
1514
add a comment |
add a comment |
No, you can't do that. There's no gcc pragma for compile in this way.
The most similar is the Microsoft Visual C++ #pragma comment(lib, …)
or #pragma comment(linker, …)
[1] [2] for noting that some libraries should be included in the link procedure.
Hi, GCC. How are you doing? In case you forgot, this source file
you're looking at right now is written in C++. You should of course
compile it with G++. There's another file that this file needs, but
it's written in C. It's called "lolcats.c". I want you to compile that
one with GCC into an object file and I want you to compile this one
with G++ into the main object file, then I want you to link them
together into an executable file.
Your request is exactly what a Makefile does.
You could create a shell script that extracts the source files and compiles them with whatever command you want to use. But it's The Wrong Solution™
If you have multiple files, store them as multiple files. If you want people not to use make or cmake, don't provide a Makefile
/CMakefile
. Give them for instance a compile-me.sh
file.
The only case when I feel I am in a similar situation is whan I code a util in a single file, but I simply provide the compilation command at the top inside a comment.
add a comment |
No, you can't do that. There's no gcc pragma for compile in this way.
The most similar is the Microsoft Visual C++ #pragma comment(lib, …)
or #pragma comment(linker, …)
[1] [2] for noting that some libraries should be included in the link procedure.
Hi, GCC. How are you doing? In case you forgot, this source file
you're looking at right now is written in C++. You should of course
compile it with G++. There's another file that this file needs, but
it's written in C. It's called "lolcats.c". I want you to compile that
one with GCC into an object file and I want you to compile this one
with G++ into the main object file, then I want you to link them
together into an executable file.
Your request is exactly what a Makefile does.
You could create a shell script that extracts the source files and compiles them with whatever command you want to use. But it's The Wrong Solution™
If you have multiple files, store them as multiple files. If you want people not to use make or cmake, don't provide a Makefile
/CMakefile
. Give them for instance a compile-me.sh
file.
The only case when I feel I am in a similar situation is whan I code a util in a single file, but I simply provide the compilation command at the top inside a comment.
add a comment |
No, you can't do that. There's no gcc pragma for compile in this way.
The most similar is the Microsoft Visual C++ #pragma comment(lib, …)
or #pragma comment(linker, …)
[1] [2] for noting that some libraries should be included in the link procedure.
Hi, GCC. How are you doing? In case you forgot, this source file
you're looking at right now is written in C++. You should of course
compile it with G++. There's another file that this file needs, but
it's written in C. It's called "lolcats.c". I want you to compile that
one with GCC into an object file and I want you to compile this one
with G++ into the main object file, then I want you to link them
together into an executable file.
Your request is exactly what a Makefile does.
You could create a shell script that extracts the source files and compiles them with whatever command you want to use. But it's The Wrong Solution™
If you have multiple files, store them as multiple files. If you want people not to use make or cmake, don't provide a Makefile
/CMakefile
. Give them for instance a compile-me.sh
file.
The only case when I feel I am in a similar situation is whan I code a util in a single file, but I simply provide the compilation command at the top inside a comment.
No, you can't do that. There's no gcc pragma for compile in this way.
The most similar is the Microsoft Visual C++ #pragma comment(lib, …)
or #pragma comment(linker, …)
[1] [2] for noting that some libraries should be included in the link procedure.
Hi, GCC. How are you doing? In case you forgot, this source file
you're looking at right now is written in C++. You should of course
compile it with G++. There's another file that this file needs, but
it's written in C. It's called "lolcats.c". I want you to compile that
one with GCC into an object file and I want you to compile this one
with G++ into the main object file, then I want you to link them
together into an executable file.
Your request is exactly what a Makefile does.
You could create a shell script that extracts the source files and compiles them with whatever command you want to use. But it's The Wrong Solution™
If you have multiple files, store them as multiple files. If you want people not to use make or cmake, don't provide a Makefile
/CMakefile
. Give them for instance a compile-me.sh
file.
The only case when I feel I am in a similar situation is whan I code a util in a single file, but I simply provide the compilation command at the top inside a comment.
answered Jul 20 '14 at 13:59
ÁngelÁngel
1,358512
1,358512
add a comment |
add a comment |
You could decide that all your things are plugins. Then compile them with gcc -shared -fPIC -O thing1.cc -o thing1.so
and have a main stub program doing dlopen(3) on ./thing1.so
then dlsym
on God
; on Linux you could have binfmt_misc tricks to make that more transparent.
If you insist on having self-containing programs, notice that GCC has the -ffreestanding option. It is then up to you to provide a runtime environment (at the very least, for some basic I/O thru system calls which you would need to interface, see syscalls(2)). Study carefully the relevant ABI spec. For Linux/x86-64 it is here. Read about calling conventions.
You could also customize GCC with compiler plugins like MELT (then you could add a #pragma
which would do arbitrary things, perhaps even forking a gcc
...)
BTW, an entry point like your God
is not a source file, but some label known to the linker.
Reading more about compilers, linkers (see Levine's book: Linkers and Loaders, object files, ELF, libraries and shared objects (see Drepper's paper: How to Write Shared Libraries ...), crt0.o should help.
See also the C++ module draft proposal N3347
add a comment |
You could decide that all your things are plugins. Then compile them with gcc -shared -fPIC -O thing1.cc -o thing1.so
and have a main stub program doing dlopen(3) on ./thing1.so
then dlsym
on God
; on Linux you could have binfmt_misc tricks to make that more transparent.
If you insist on having self-containing programs, notice that GCC has the -ffreestanding option. It is then up to you to provide a runtime environment (at the very least, for some basic I/O thru system calls which you would need to interface, see syscalls(2)). Study carefully the relevant ABI spec. For Linux/x86-64 it is here. Read about calling conventions.
You could also customize GCC with compiler plugins like MELT (then you could add a #pragma
which would do arbitrary things, perhaps even forking a gcc
...)
BTW, an entry point like your God
is not a source file, but some label known to the linker.
Reading more about compilers, linkers (see Levine's book: Linkers and Loaders, object files, ELF, libraries and shared objects (see Drepper's paper: How to Write Shared Libraries ...), crt0.o should help.
See also the C++ module draft proposal N3347
add a comment |
You could decide that all your things are plugins. Then compile them with gcc -shared -fPIC -O thing1.cc -o thing1.so
and have a main stub program doing dlopen(3) on ./thing1.so
then dlsym
on God
; on Linux you could have binfmt_misc tricks to make that more transparent.
If you insist on having self-containing programs, notice that GCC has the -ffreestanding option. It is then up to you to provide a runtime environment (at the very least, for some basic I/O thru system calls which you would need to interface, see syscalls(2)). Study carefully the relevant ABI spec. For Linux/x86-64 it is here. Read about calling conventions.
You could also customize GCC with compiler plugins like MELT (then you could add a #pragma
which would do arbitrary things, perhaps even forking a gcc
...)
BTW, an entry point like your God
is not a source file, but some label known to the linker.
Reading more about compilers, linkers (see Levine's book: Linkers and Loaders, object files, ELF, libraries and shared objects (see Drepper's paper: How to Write Shared Libraries ...), crt0.o should help.
See also the C++ module draft proposal N3347
You could decide that all your things are plugins. Then compile them with gcc -shared -fPIC -O thing1.cc -o thing1.so
and have a main stub program doing dlopen(3) on ./thing1.so
then dlsym
on God
; on Linux you could have binfmt_misc tricks to make that more transparent.
If you insist on having self-containing programs, notice that GCC has the -ffreestanding option. It is then up to you to provide a runtime environment (at the very least, for some basic I/O thru system calls which you would need to interface, see syscalls(2)). Study carefully the relevant ABI spec. For Linux/x86-64 it is here. Read about calling conventions.
You could also customize GCC with compiler plugins like MELT (then you could add a #pragma
which would do arbitrary things, perhaps even forking a gcc
...)
BTW, an entry point like your God
is not a source file, but some label known to the linker.
Reading more about compilers, linkers (see Levine's book: Linkers and Loaders, object files, ELF, libraries and shared objects (see Drepper's paper: How to Write Shared Libraries ...), crt0.o should help.
See also the C++ module draft proposal N3347
edited Jul 20 '14 at 13:17
answered Jul 20 '14 at 11:31
Basile StarynkevitchBasile Starynkevitch
8,0862041
8,0862041
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f145527%2fcompiling-c-c-code-by-way-of-including-preprocessor-build-instructions-in-an-a%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You could decide that all your things are plugins.
– Basile Starynkevitch
Jul 20 '14 at 11:29
3
Your question is unclear.
– Basile Starynkevitch
Jul 20 '14 at 11:39