How to link multiple files in Turbo C++? - c++

I know Turbo C++ is oudated as hell, but so is the curriculum of our central board in my country (India). And I am doing a school project. And I don't have the freedom to choose my own IDE and compiler. Go figure.
NOTE: I am using Turbo C++ 3.0 in DOSBox in Win10
Anyway, here is the project directory I made to test TC++'s linking:
TC/BIN
-MAIN.CPP
#include <iostream.h>
#include <conio.h>
#include "CL.H"
int main()
{
clrscr();
cout<<"HW";
cl c;
c.set(5);
cout<<c.get();
getch();
return 0;
}
-CL.CPP
#include "CL.H"
void cl::set( int i )
{
a = i;
}
int cl::get()
{
return a;
}
-CL.H
#ifndef CL_H
#define CL_H
class cl
{
int a;
public:
void set( int i);
int get();
};
#endif
All of these compile fine. Upon trying to link, I get the following linker error:
LINKER ERROR: Undefined symbol cl::get() in module MAIN.CPP
LINKER ERROR: Undefined symbol cl::set( int ) in module MAIN.CPP

You can do that:
1- Open TC.exe
2- From project select Open Project
3- Enter the name of project eg: MyProj.prj and Press ok.
4- From project select Add item
5- Locate all the source files and add them.
6- compile and build.

(Posted on behalf of the question author).
I had the .h files also added to the project. That caused all the trouble. Removing the .h files from the project seems to make it work.

Related

How to add a new class to the chromium source code? Linker won't see the new header and .cc files with the new class

I am working on a project that deals with ungoogled-chromium. Part of my task is to change some parameters that are spread across multiple header files. The idea was to have a custom class that would load data from a config file, save it to the variables in a custom class and then update the needed parameters in different classes.
Additional info:
-I am building Chromium in release mode, not component.
-My idea was to put this class in src/base, as I want to reuse this in other classes, and I figured it should be put somewhere in the lower levels.
-I am not the best with C++
The idea works in a separate, smaller solution that I built as a test, but it fails to work properly in chromium. Here are the header and .cc files:
variables.h
#ifndef VARIABLES_H
#define VARIABLES_H
namespace base {
class GlobVars {
public:
static void updateVars();
static int getDevMem();
private:
// config vars
static int device_memory;
static double battery_percentage;
//static std::string user_agent, platform;
};
} // namespace base
#endif
variables.cc
#include "variables.h"
namespace base {
int GlobVars::device_memory = 0;
double GlobVars::battery_percentage = 0;
//std::string GlobVars::user_agent = "", GlobVars::platform = "";
void GlobVars::updateVars() {
device_memory = 456;
battery_percentage = 0.768;
}
int GlobVars::getDevMem(){
return device_memory;
}
} // namespace base
And here is where I try to use the function getDevMem():
#include "third_party/blink/public/common/device_memory/approximated_device_memory.h"
#include "base/check_op.h"
#include "base/system/sys_info.h"
#include "base/variables.h"
namespace blink {
// static
float ApproximatedDeviceMemory::approximated_device_memory_gb_ = 0.0;
int64_t ApproximatedDeviceMemory::physical_memory_mb_ = 0;
// static
float ApproximatedDeviceMemory::GetApproximatedDeviceMemory() {
return ::base::GlobVars::getDevMem();
//return approximated_device_memory_gb_;
}
} // namespace blink
Here is the specific error message I keep getting:
FAILED: chromedriver_unittests.exe chromedriver_unittests.exe.pdb
..\\..\\third_party\\llvm-build\\Release+Asserts\\bin\\lld-link.exe /OUT:./chromedriver_unittests.exe /nologo -libpath:..\\..\\third_party\\llvm-build\\Release+Asserts\\lib\\clang\\16.0.0\\lib\\windows "-libpath:../../../../../../../Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.33.31629/ATLMFC/lib/x64" "-libpath:../../../../../../../Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.33.31629/lib/x64" "-libpath:../../../../../../../Program Files (x86)/Windows Kits/NETFXSDK/4.8/lib/um/x64" "-libpath:../../../../../../../Program Files (x86)/Windows Kits/10/lib/10.0.20348.0/ucrt/x64" "-libpath:../../../../../../../Program Files (x86)/Windows Kits/10/lib/10.0.20348.0/um/x64" /MACHINE:X64 /PDB:./chromedriver_unittests.exe.pdb #./chromedriver_unittests.exe.rsp
lld-link: error: undefined symbol: public: static int \__cdecl base::GlobVars::getDevMem(void)
\\\>\>\> referenced by ../../third_party/blink/common/device_memory/approximated_device_memory.cc
\\\>\>\> obj/third_party/blink/common/common/approximated_device_memory.obj
\[15619/17044\] CXX obj/v8/torque_generated_definitions/js-objects-tq.obj
ninja: build stopped: subcommand failed.
I figured that just including the header file would be sufficient to access the static variables but I keep getting undefined symbol error. My first approach was to try using the extern keyword but since that is more C like, I went with class implementation, but I still have the same issue.
I got it working, I had to edit BUILD.gn files in separate folders to include .h and .cc files.

Visual Studio's Test Explorer breaks when trying to link object files

I want to use Visual Studio's Test Explorer to run my Google Tests. When I create a console project and add a default Google Test project, and build the solution, it finds the tests as intended.
Now I want to create my own class, where everything is set up in the header file.
class foo
{
public:
foo() : the_count(0) {}
~foo() = default;
void count_plus() { the_count++; };
int get_count() { return the_count; };
private:
int the_count;
};
Then I modify my test.cpp file (the default file created by Visual Studio's Google Test project) to make use of my new class.
#include "pch.h"
#include <iostream>
#include "..\ConsoleApplication2\foo.h"
class tester : public testing::Test {
public:
foo bar;
void SetUpTestSuite() {
std::cout << "Setup..\n";
}
void TearDownTestSuite() {
std::cout << "Teardown..\n";
}
};
TEST_F(tester, TestFixture1)
{
EXPECT_EQ(bar.get_count(), 0);
bar.count_plus();
EXPECT_EQ(bar.get_count(), 1);
}
Building this solution also automatically detects the tests and runs them succesfully.
Now it gets interesting... When I move my implementation of foo to a .cpp file.
foo.h
class foo
{
public:
foo();
~foo() = default;
void count_plus();
int get_count();
private:
int the_count;
};
foo.cpp
#include "foo.h"
foo::foo()
{
the_count = 0;
}
void
foo::count_plus()
{
the_count++;
}
int
foo::get_count()
{
return the_count;
}
And then I build the solution, I initially get a linker error complaining about unresolved externals.
However, if I change the test project's linker settings to point to the other project like so:
Properties -> Linker -> Input -> Additional Dependencies -> add $(SolutionDir)ConsoleApplication2\$(IntDir)*.obj
which I got from this answer, I can succesfully build the project.
However, after I finish building the project, I'm no longer able to see or run my tests.
Am I doing something wrong here? Or is Visual Studio just broken?
I figured it out. The project which generates the object files cannot have a main() function, as this overrides Google Test's main() function.
I solved it by:
Creating an empty project (with no main()) which contains all my source code and set this project's Configuration Type as Static library (.lib).
Creating a console application project (or whatever suits your needs) which contains my main() entry point. In this project, I add a reference to my .lib project.
Create a Google Test project. In this project, I also add a reference to my .lib project.
Set the project in step two as the Startup project.
Now when you want to run your code, it will run it from your one entry point, but grab the source from .lib project and your Google Test project will also grab this .lib file, detecting all your tests.

How to make CPP files visible to linker in ESP8266 Eclipse project

There is a "hello world" project in Eclipse IDE that is supposed to compile against ESP8266 RTOS SDK.
File structure is as follows
I added one C++ class to it and put it into its own folder. Here is the class header
#ifndef MAIN_BLINKER_BLINKER_H_
#define MAIN_BLINKER_BLINKER_H_
class Blinker {
public:
Blinker( int period );
int Period() const;
private:
int period_;
};
#endif /* MAIN_BLINKER_BLINKER_H_ */
and the definitions
#include "Blinker.h"
Blinker::Blinker( int period ) :
period_( period )
{}
int Blinker::Period() const {
return this->period_;
}
Main.cpp file is like this
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "blinker/Blinker.h"
extern "C" {
void app_main()
{
auto blnk = Blinker( 3000 );
int i = 0;
while ( 1 ) {
printf( "[%d] Hello beautiful world!\n", i );
i++;
vTaskDelay( blnk.Period() / portTICK_PERIOD_MS );
}
}
}
It compiles but fails at final stage because the linker (or what is supposed to be a linker in xtensa toolchain) does not see definitions of Blinker methods. This is what I get in the build log
If I put class files next to main.cpp file, the build succeeds. However with time there will be hundreds of files, and without any grouping it will quickly turn into an unmanageable mess.
Alternatively I could put this class into top-level components folder and equip it with empty component.mk file. This would also make the build system happy, however it would force me to use ugly header includes like ../components/blinker/Blinker.h, which I would like to avoid.
So the question is how to make build system aware of .c and .cpp files residing in subfolders of main folder?
you can set COMPONENT_SRCDIRS in "main" component.mk file
see:
https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/api-guides/build-system.html#example-component-makefiles
Try to add blinker/Blinker.cpp to your CMakeLists.txt.
Take a look at
How to add new source file in CMakeLists.txt?

Codelite linker undefined reference error

I'm new to codelite and c++. I'm using Linux and the g++ compiler. I've set up a simple project with two source files just to play around with linker errors. The files look like so:
Main.cpp:
#include <iostream>
void Log(const char*);
static int Multiply (int a, int b)
{
Log("Multiply");
return a * b;
}
int main()
{
std::cout << Multiply(5, 8) << std::endl;
std::cin.get();
}
Log.cpp:
#include <iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
As you can see, Log.cpp simply specifies a function called in main. Both files are in the same directory, "src". So far all my settings are pretty much default, still I get an "undefined reference to `Log(..." error when I try to build this project.
Also, if I comment out the declaration of the Log function at the top of main.cpp, I would expect a compilation error since an undeclared function being called. Yet if I try to compile main.cpp I get no errors.
This is what my workspace looks like
Project settings
Compiler settings
Linker settings
Am I correct to expect the behaviors described above? Is there some setting I have to manually configure?

Including STL in static libraries

I have created a static library with the files alien.h and alien.cpp below. That library is linked by the file user.cpp. If one removes the line with the comment, then the code compiles, links, and runs as expected. As it is, the library and the program compile, the program however does not link. MSVC2015RC generates over 100 errors about std::numeric_limits being already defined.
Is there some setting that I should be aware of or is this a MSVC2015 bug?
File alien.h
#include <vector> // This line causes troubles.
struct alien
{
const int * const value;
};
extern alien meh;
File alien.cpp
alien meh { 7 };
File user.cpp
#include "alien.h"
#include <iostream>
#pragma comment(lib, "alien.lib")
int main()
{
wcout << meh.value;
return 0;
}
Error LNK2005 "public: static int const std::numeric_limits::max_exponent" (?max_exponent#?$numeric_limits#M#std##2HB) already defined in alien.obj
It is a bug! The same library/program compiles under MSVC2013 without language extensions enabled. In MSVC2015, language extensions must be enabled.