0

Good morning, I new in c++ and I am trying to compile my simple code to executable form. I will explain structure of project.

- main.cpp
- /utility/server.h
- /utility/server.cpp

I enclose file sources for complete information. main.cpp

#include <iostream>
#include "utility/server.h"

using namespace std;
using namespace server;

int main() {
    std::cout << "Content-type:text/html\r\n\r\n";
    std::cout << "Your server name is: " << server::get_domain() << '\n';
    return 0;
}

server.cpp

#include <cstdlib>
#include "server.h"

namespace server {
    static char* get_domain() {
        return getenv("SERVER_NAME");
    }
}

To my Makefile I added comments to understand what I want to do.

#
# 'make'        build executable file 
# 'make clean'  removes all .o and executable files
#

# define the C compiler to use
CC = g++

# define any compile-time flags
CFLAGS = -Wall -g

# define any directories containing header files other than /usr/include
INCLUDES = -I../utility

# define the C++ source files
SRCS = main.cpp utility/server.cpp

# define the C++ object files 
OBJS = $(SRCS:.cpp=.o)

# define the executable file 
MAIN = executable.cgi

#
# The following part of the makefile is generic
#

.PHONY: depend clean

all:    $(MAIN)

$(MAIN): $(OBJS) 
        $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS)

# this is a suffix replacement rule for building .o's from .cpp's
.c.o:
        $(CC) $(CFLAGS) $(INCLUDES) -cpp $<  -o $@

clean:
        $(RM) *.o *~ $(MAIN)

depend: $(SRCS)
        makedepend $(INCLUDES) $^

And finally error from compilation

g++ -Wall -g -I../utility -o executable.cgi main.o utility/server.o
Undefined symbols for architecture x86_64:
  "server::get_domain()", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [executable.cgi] Error 1

From error message I understood there is problem with utility folder, but I don't know how to fix it. Thank you for your help :)

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
Amateur
  • 43
  • 6
  • And BTW, do see [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/q/1452721/1362568) – Mike Kinghan May 24 '20 at 10:54

1 Answers1

0

In server.cpp, here:

namespace server {
    static char* get_domain() {
        return getenv("SERVER_NAME");
    }
}

You have made char* server::get_domain() a static function, making its definition visible only within this translation unit and invisible to the linker. Remove the keyword static here, and also in server.h if you have declared the function static there.

A namespace is not a class or struct. Confusingly,

namespace server {
    static char* get_domain() {
        return getenv("SERVER_NAME");
    }
}

server::get_domain() is a static function in that namespace. But

struct server {
    static char* get_domain() {
        return getenv("SERVER_NAME");
    }
};

it is a global function in that class, which the linker can see.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182